/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ProOF.apl.problems.real;

import ProOF.apl.methods.GA.population.aPopulation;
import ProOF.apl.problems.real.functions.aRealFunction;
import ProOF.com.Communication;
import ProOF.com.LinkerNodes;
import ProOF.com.LinkerParameters;
import ProOF.com.LinkerResults;
import ProOF.com.LinkerValidations;
import ProOF.com.StreamProgress;
import ProOF.gen.best.nEvaluations;
import ProOF.gen.stopping.aStop;
import ProOF.opt.abst.problem.meta.Solution;
import java.util.ArrayList;

/**
 *
 * @author hossomi
 */
public final class iStopStdDev extends aStop{
    public static final iStopStdDev obj = new iStopStdDev();
    
    private aPopulation         pop;
    private ArrayList<Solution> individuals;
    private StreamProgress      prog;
    
    private double margin;
    private double factor;
    
    @Override
    public String name() {
        return "Stop for Std. Dev.";
    }
    
    @Override
    public String description() {
        throw new UnsupportedOperationException("Not supported yet.");
    }
    
    @Override
    public void services(LinkerNodes win) throws Exception {
        pop = win.need(aPopulation.class, pop);
    }
    
    @Override
    public void parameters(LinkerParameters win) throws Exception {
        margin = win.Dbl("Stop Std. Dev.", 1e-6, 0, 1e6);
    }
    
    @Override
    public void load() throws Exception {
        prog = Communication.mkProgress("Convergence");
    }

    @Override
    public void start() throws Exception {
        super.start();
        individuals = pop.getIndividuals();
    }
    
    @Override
    public boolean validation(LinkerValidations win) throws Exception {
        return true;
    }
    
    @Override
    public double progress() throws Exception {
        prog.progress(factor);
        return factor;
    }  
    
    @Override
    public boolean end() throws Exception {
        double average = 0;
        double stddev = 0;
        
        if (individuals.size() < pop.getSize()) {
            factor = 0;
            return false;
        }
        
        for (Solution s: individuals) 
            average += pop.getFitness(s) / individuals.size();
        
        for (Solution s: individuals) 
            stddev += Math.pow(pop.getFitness(s) - average, 2) / individuals.size();
        
        stddev = Math.sqrt(stddev);
        factor = 1.0 - (stddev - margin)/stddev;
        progress();
        
        return factor >= 1.0;
    }

    @Override
    public void results(LinkerResults com) throws Exception {
        super.results(com);
    }
}
